﻿using System.Collections.Generic;
using System.Linq;

namespace AutoUnitTest.Common
{
    public class Graph
    {
        private List<VertexType> vertexTypes = new List<VertexType>();
        private List<EdgeType> edgeTypes = new List<EdgeType>();

        public bool IsValid { get; private set; }
        public virtual List<Vertex> VertexList { get; private set; }
        public virtual List<Edge> EdgeList { get; private set; }

        public Graph()
        {
            
        }

        public Graph(List<Vertex> vertexes, List<Edge> edges)
            :this(vertexes,edges,true){}

        public Graph(List<Vertex> vertexes, List<Edge> edges, bool val)
        {
            IsValid = val;

            VertexList = vertexes;
            EdgeList = edges;

            foreach (var v in VertexList)
                foreach (var e in EdgeList)
                {
                    if (e.StartVertex == v)
                        v.OutgoingEdges.Add(e);
                    if (e.EndVertex == v)
                        v.IncomingEdges.Add(e);
                }
        }

        private VertexType findVertexTypeByName(string name)
        {
            var vxs = from x in VertexList
                      where x.Type.Name == name
                      select x;

            return vxs.Any() ? vxs.First().Type : null;
        }

        private EdgeType findEdgeTypeByName(string name)
        {
            return (from e in EdgeList where e.Type.Name.Equals(name) select e.Type).FirstOrDefault();
        }

        public List<VertexType> getVertexTypes()
        {
            foreach (Vertex v in VertexList.Where(v => !vertexTypes.Contains(v.Type)))
            {
                vertexTypes.Add(v.Type);
            }
            return vertexTypes;
        }

        public List<EdgeType> getEdgeTypes()
        {
            foreach (Edge e in EdgeList.Where(e => !edgeTypes.Contains(e.Type)))
            {
                edgeTypes.Add(e.Type);
            }
            return edgeTypes;
        }

        public List<Vertex> TypedVertexList(VertexType type)
        {
            return VertexList.Where(v => v.Type == type).ToList();
        }
        public List<Edge> TypedEdgeList(EdgeType type)
        {
            return EdgeList.Where(e => e.Type == type).ToList();
        }
        public bool AddVertex(Vertex vertex)
        {
            var type = findVertexTypeByName(vertex.Type.Name);
            if (null != type)
                vertex.Type = type;
            VertexList.Add(vertex);
            return true;
        }
        public bool AddEdge(Edge edge)
        {
            var type = findEdgeTypeByName(edge.Type.Name);
            if (null != type)
                edge.Type = type;
            EdgeList.Add(edge);
            return true;
        }
    }
}